package jinyilw.tools.net;

import jinyilw.common.SettingTools;
import jinyilw.common.app.AppConfig;
import jinyilw.common.file.FileTools;
import jinyilw.common.file.Transfer;
import jinyilw.common.file.TransferTools;
import jinyilw.common.hint.HintTools;
import jinyilw.common.log.LogTools;
import jinyilw.tools.net.dev.BaseClient;
import jinyilw.tools.net.dev.CommandPacket;
import jinyilw.tools.net.dev.NetworkPacket;

public class UpdateTools
{
	public static final boolean isUpdating = SettingTools
			.getDefaultBool("isUpdating", false);
	public static final short checkUpdate = -100;
	public static final short manualUpdate = -101;
	public static final short autoUpdate = -102;

	private static ServerTools updateServerTools;
	private static ClientTools updateClientTools;
	private static Boolean isUpdateServer;

	private static Transfer updateTransfer;

	static
	{
		if (isUpdating)
			AppConfig.addAppExitingOperator(
					o -> SettingTools.putDefaultSettingData("isUpdating", false));
	}

	private UpdateTools()
	{
	}

	public static boolean isUpdateServer()
	{
		if (isUpdateServer == null)
			isUpdateServer = NetConfig.getUpdateServerIP().equals(NetTools.getHostIP());
		return isUpdateServer;
	}

	public static void startUpdateServerTools()
	{
		if (updateServerTools == null)
			updateServerTools = new ServerTools(
					NetConfig.getUpdateTCPParameter())
					.enableUpdate();
		updateServerTools.start();
	}

	public static ClientTools startUpdateClientTools()
	{
		if (updateClientTools == null)
			updateClientTools = new ClientTools(
					NetConfig.getUpdateTCPParameter());
		updateClientTools.connect();
		return updateClientTools;
	}

	public static ClientTools getUpdateClientTools()
	{
		return updateClientTools;
	}

	public static boolean manualCheckUpdate(BaseClient c)
	{
		if (c != null && c.isConnected())
		{
			CommandPacket packet = new CommandPacket(checkUpdate);
			packet.setIntData(AppConfig.appVersion);
			c.sendCommand(packet);
			return true;
		}
		HintTools.hint("检查更新", "未连接到服务器，请稍后再试！");
		return false;
	}

	public static void autoCheckUpdate(BaseClient c)
	{
		if (c != null && c.isConnected())
		{
			CommandPacket packet = new CommandPacket(autoUpdate);
			packet.setIntData(AppConfig.appVersion);
			c.sendCommand(packet);
		}
	}

	public static void handleUpdate(BaseClient client)
	{
		for (NetworkPacket packet : client.getReceivedPackets())
			if (packet instanceof CommandPacket)
				handleUpdate(client, (CommandPacket) packet);
	}

	public static void handleUpdateInThread(BaseClient client)
	{
		for (NetworkPacket packet : client.getReceivedPackets())
			if (packet instanceof CommandPacket)
				handleUpdateInThread(client, (CommandPacket) packet);
	}

	private static void handleUpdate(BaseClient c, CommandPacket packet)
	{
		int command = packet.getCommandID();
		if (command == checkUpdate)
		{
			boolean canUpdate = AppConfig.appVersion > packet.getIntData();
			packet.setCommandID(manualUpdate);
			packet.setBoolData(canUpdate);
			if (canUpdate)
			{
				packet.setIntData(NetTools.getLocalAvailablePort());
			}
			c.sendCommand(packet);
		} else if (command == manualUpdate)
		{
			LogTools.info(">>>" + c.getInfo() + " 开始更新...");
			TransferTools.sendFileToNetTemporarily(packet.getIntData(),
					AppConfig.getAppExeFile(), null);
			LogTools.info(">>>" + c.getInfo() + " 更新完成");
		} else if (command == autoUpdate)
		{
			if (AppConfig.appVersion > packet.getIntData())
			{
				int port = NetTools.getLocalAvailablePort();
				packet.setIntData(port);
				c.sendCommand(packet);
				LogTools.info(">>>" + c.getInfo() + " 开始更新...");
				TransferTools.sendFileToNetTemporarily(port,
						AppConfig.getAppExeFile(), null);
				LogTools.info(">>>" + c.getInfo() + " 更新完成");
			}
		}
	}

	private static void handleUpdateInThread(BaseClient c, CommandPacket packet)
	{
		int command = packet.getCommandID();
		if (command != checkUpdate && command != manualUpdate
				&& command != autoUpdate)
			return;
		new Thread(() -> handleUpdate(c, packet)).start();
	}

	public static void clientUpdate(ClientTools c, CommandPacket packet)
	{
		int command = packet.getCommandID();
		if (command == manualUpdate)
			clientManualUpdate(c, packet);
		else if (command == autoUpdate)
			clientAutoUpdate(c, packet);
	}

	public static void clientUpdateInThread(ClientTools c, CommandPacket packet)
	{
		int command = packet.getCommandID();
		if (command != manualUpdate && command != autoUpdate)
			return;
		new Thread(() -> clientUpdate(c, packet)).start();
	}

	public static void clientManualUpdate(ClientTools c, CommandPacket packet)
	{
		if (packet.getCommandID() != manualUpdate)
			return;
		boolean canUpdate = packet.getBoolData();
		if (canUpdate && HintTools.confirm("检查更新",
				"当前有可用更新！是否开始下载更新？"))
		{
			c.sendCommand(packet);
			String ip = c.getServerIP();
			int port = packet.getIntData();
			try
			{
				Thread.sleep(1000);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			TransferTools.receiveFileFromNetTemporarily(ip, port,
					FileTools.createDirectory("tmp"), getUpdateTransfer());
		}
		if (!canUpdate)
			HintTools.hint("检查更新", "当前版本为最新，无需更新！");
	}

	public static void clientAutoUpdate(ClientTools c, CommandPacket packet)
	{
		if (packet.getCommandID() != autoUpdate)
			return;
		String ip = c.getServerIP();
		int port = packet.getIntData();
		try
		{
			Thread.sleep(500);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		TransferTools.receiveFileFromNetTemporarily(ip, port,
				FileTools.createDirectory("tmp"), getUpdateTransfer());
	}

	public static void setUpdateTransfer(Transfer transfer)
	{
		updateTransfer = transfer;
	}

	public static Transfer getUpdateTransfer()
	{
		return updateTransfer;
	}

	public static void restartAppToUpdate()
	{
		AppConfig.addAppExitingOperator(
				o -> SettingTools.putDefaultSettingData("isUpdating", true));
		AppConfig.restartAppToUpdate();
	}
}
